package cn.ynrcb.personnelfile.sysadmin.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.ynrcb.personnelfile.admin.enums.UserLoginTypeEnum;
import cn.ynrcb.personnelfile.common.exception.MyException;
import cn.ynrcb.personnelfile.common.utils.PageUtils;
import cn.ynrcb.personnelfile.common.utils.ValidatorUtils;
import cn.ynrcb.personnelfile.sysadmin.constant.SysConstant;
import cn.ynrcb.personnelfile.sysadmin.dao.SysOrgDao;
import cn.ynrcb.personnelfile.sysadmin.dao.SysUserDao;
import cn.ynrcb.personnelfile.sysadmin.entity.SysDictEntity;
import cn.ynrcb.personnelfile.sysadmin.entity.SysOrgEntity;
import cn.ynrcb.personnelfile.sysadmin.entity.SysUserEntity;
import cn.ynrcb.personnelfile.sysadmin.service.*;
import cn.ynrcb.personnelfile.sysadmin.service.*;
import cn.ynrcb.personnelfile.sysadmin.vo.UserListVo;
import cn.ynrcb.personnelfile.sysadmin.vo.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private CurrentUserService currentUserService;
    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private SysOrgDao sysOrgDao;
    @Autowired
    private SysOrgService sysOrgService;

    @Override
    public PageUtils queryAuditPage(Map<String, Object> params) {
        Page<UserListVo> page = new Page<UserListVo>(Convert.toLong(params.get("page"), 1L), Convert.toLong(params.get("limit"), 10L));
        List<UserListVo> list = baseMapper.queryAuditUserPage(page, params);
        page.setRecords(list);
        return new PageUtils((IPage<?>) page);
    }

    @Override
    public PageUtils queryPageAdmin(Map<String, Object> params) {
        Page<UserListVo> page = new Page<UserListVo>(Convert.toLong(params.get("page"), 1L), Convert.toLong(params.get("limit"), 10L));
        List<UserListVo> list = baseMapper.queryQyAdminUserPage(page, params);
        page.setRecords(list);
        return new PageUtils((IPage<?>) page);
    }

    @Override
    public List<String> queryAllPerms(Long userId) {
        return baseMapper.queryAllPerms(userId);
    }

    @Override
    public List<Long> queryAllMenuId(Long userId) {
        return baseMapper.queryAllMenuId(userId);
    }

    @Override
    @Transactional
    public void userRegister(UserVo.UserRegisterParams params) {
        //验证用户名规则
        if (!ValidatorUtils.isMobile(params.getUsername())) {
            throw new MyException("该手机号不符合规则！");
        }
        //验证手机号是否与其他用户的绑定手机相重复
        if (ObjectUtil.isNotNull(this.queryByMobile(params.getMobile()))) {
            throw new MyException("该手机号已被注册！");
        }
        //验证密码规则
        if (!ValidatorUtils.checkPasswordRule(params.getPassword())) {
            throw new MyException("该密码不符合规则！");
        }
        //验证统一社会信用代码是否已存在
        if (ObjectUtil.isNotNull(sysOrgDao.getOrgByCreditCode(params.getCreditCode()))) {
            throw new MyException("您输入的统一社会信用代码已存在，请勿重复注册！");
        }
        //生成机构信息
        SysOrgEntity org = new SysOrgEntity();
        org.setOrgName(params.getOrgName());
        org.setCreditCode(params.getCreditCode());
        //注册的协会机构暂时禁用
        org.setStatus(2);
        org.setPId(Long.valueOf(1));
        //保存
        sysOrgService.saveOrg(org);
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        params.setPassword(new Sha256Hash(params.getPassword(), salt).toHex()); //密码加密
        //生成用户信息
        SysUserEntity user = new SysUserEntity();
        BeanUtils.copyProperties(params, user);
        user.setSalt(salt);
        List<Integer> roleIdList = new ArrayList<>();
        //设置协会人员角色id
        roleIdList.add(10);
        user.setRoleId(roleIdList.get(0));
        user.setRoleIdList(roleIdList);
        user.setUsername(params.getMobile());
        //注册的用户需要审核
        user.setAuditStatus(2);
        user.setOrgId(sysOrgDao.getOrgByCreditCode(org.getCreditCode()).getId());
        this.save(user);
        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
    }

    @Override
    @Transactional
    public void update(SysUserEntity user, Integer optflag) {
        if (StringUtils.isBlank(user.getPassword())) {
            user.setPassword(null);
        } else {
            String salt = this.getById(user.getUserId()).getSalt();
            user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
        }
        user.setRoleId(user.getRoleIdList().get(0));
        this.updateById(user);

        //检查角色是否越权
//		checkRole(user);
        //保存用户与角色关系
        if (2 == optflag) {//非企业微信用户绑定操作
            sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
        }
    }

    @Override
    public void deleteBatch(Long[] userId) {
        this.removeByIds(Arrays.asList(userId));
    }

    @Override
    public boolean updatePassword(Long userId, String password, String newPassword) {
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setPassword(newPassword);
        return this.update(userEntity,
                new QueryWrapper<SysUserEntity>().eq("user_id", userId).eq("password", password));
    }

    public boolean setPassword(Long userId, String newPassword, String salt) {
        sysUserRoleService.saveUserAndRole(userId, 99);
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setPassword(newPassword);
        userEntity.setSalt(salt);
        return this.update(userEntity,
                new QueryWrapper<SysUserEntity>().eq("user_id", userId));
    }

    /**
     * 检查角色是否越权
     */
    private void checkRole(SysUserEntity user) {
        if (user.getRoleIdList() == null || user.getRoleIdList().size() == 0) {
            return;
        }
        //如果不是超级管理员，则需要判断用户的角色是否自己创建
        if (user.getCreateUserId() == SysConstant.SUPER_ADMIN_ROLE_ID) {
            return;
        }

        //查询用户创建的角色列表
        List<Integer> roleIdList = sysRoleService.queryRoleIdList(user.getCreateUserId());

        //判断是否越权
        if (!roleIdList.containsAll(user.getRoleIdList())) {
            throw new MyException("新增用户所选角色，不是本人创建");
        }
    }

    @Override
    public void resetPassword(Long userId, String password) {
        SysUserEntity user = this.getById(userId);
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        user.setPassword(new Sha256Hash(password, salt).toHex()); //设置默认密码
        user.setSalt(salt);
        this.updateById(user);
    }

    @Override
    public Map<String, String> getUserInfo(String username) {
        return baseMapper.getUserInfo(username);
    }

    @Override
    public boolean forgetPassword(UserVo.UserForgetParams params) {
        //验证密码规则
        if (!ValidatorUtils.isPassword(params.getNewPassword())) {
            throw new MyException("必须包含大小写字母和数字的组合，可以使用特殊字符，长度在 6-20 之间！");
        }
        //找到用户信息
        SysUserEntity user;
        //获取登录用户信息
        user = this.getOne(new QueryWrapper<SysUserEntity>().eq("mobile", params.getMobile()).ne("status", -1));
        if (ObjectUtil.isNull(user)) {
            throw new MyException("该手机号未绑定用户！");
        }
        //sha256加密
        //盐值不为空，则为新系统用户改密码
        if (org.apache.commons.lang3.StringUtils.isNotBlank(user.getPassword())) {
            params.setNewPassword(new Sha256Hash(params.getNewPassword(), user.getSalt()).toHex()); //设密码加密
            return updatePassword(user.getUserId(), user.getPassword(), params.getNewPassword());
        } else {
            String salt = RandomStringUtils.randomAlphanumeric(20);
            params.setNewPassword(new Sha256Hash(params.getNewPassword(), salt).toHex()); //设密码加密
            return setPassword(user.getUserId(), params.getNewPassword(), salt);
        }
    }

    @Override
    public void bindMobileAndEmail(UserVo.UserBindParams params) {
//		//验证邮箱规则
//		if(!ValidatorUtils.isEmail(params.getEmail())){
//			throw new MyException("该邮箱不符合规则！");
//		}
        //验证手机号规则
        if (!ValidatorUtils.isMobile(params.getMobile())) {
            throw new MyException("该手机号不符合规则！");
        }
        SysUserEntity user = this.getById(currentUserService.getUserId());
//		user.setEmail(params.getEmail());
        user.setMobile(params.getMobile());
        user.setUpdateUserId(currentUserService.getCurrentUserId());
        user.setUpdateTime(new Date());
        this.updateById(user);
    }

    @Override
    public void replaceBind(UserVo.UserReplaceBindParams params) {
        //验证手机号规则
        if (!ValidatorUtils.isMobile(params.getMobile())) {
            throw new MyException("该手机号不符合规则！");
        }

        SysUserEntity user = this.getById(currentUserService.getUserId());
        user.setMobile(params.getMobile());
        user.setUpdateUserId(currentUserService.getCurrentUserId());
        user.setUpdateTime(new Date());
        this.updateById(user);
    }

    @Override
    public Integer getLoginType(Long userId, UserVo.UserLoginVo loginUser) {
        SysUserEntity user = this.getById(userId);
        //判断是否为管理员
        if (ObjectUtil.isNotNull(user.getRoleId()) && user.getRoleId() < 10) {
            return UserLoginTypeEnum.ADMIN.getCode();
        }
        //非管理员时，判断是否填报了当前年的企业信息年表
        if (ObjectUtil.isNotNull(1)) {
            //当前年的企业信息年表不为空
            return UserLoginTypeEnum.USER_EXIST_ENTERPRISE_INFO.getCode();
        } else {
            //未绑定
            return UserLoginTypeEnum.USER_NO_EXIST_ENTERPRISE_INFO.getCode();
        }
    }

    @Override
    public void switchState(Long userId) {
        SysUserEntity user = this.getById(userId);
        user.setStatus(user.getStatus() == 1 ? 0 : 1);
        user.setUpdateUserId(currentUserService.getUserId());
        user.setUpdateTime(new Date());
        this.updateById(user);
    }


    @Override
    public void lockState(Long userId) {
        SysUserEntity user = this.getById(userId);
        user.setIsLock(user.getIsLock() == 1 ? 0 : 1);
        user.setUpdateUserId(currentUserService.getUserId());
        user.setUpdateTime(new Date());
        this.updateById(user);
    }

    @Override
    public SysUserEntity queryByUserName(String username) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username.trim())
                .ne("status", -1);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public SysUserEntity queryByMobile(String username) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", username.trim())
                .ne("status", -1)
                .last("limit 1");
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    @Transactional
    public void saveUser(SysUserEntity user) {
        String password = "";
        if (StringUtils.isNotBlank(user.getPassword())) {
            //输入的密码不为空则使用输入的密码
            password = user.getPassword();
        } else {
            //输入的密码为空则使用默认密码
            SysDictEntity dict = sysDictService.getOne(
                    new QueryWrapper<SysDictEntity>()
                            .eq("type", "password")
                            .eq("label", "password")
            );
            password = dict.getValue();
        }

        SysUserEntity existUser = this.getOne(
                new QueryWrapper<SysUserEntity>()
                        .eq("username", user.getUsername())
                        .ne("status", -1)
        );
        if (null != existUser && null != existUser.getUsername()) {
            throw new MyException("当前账号已经录入了，请不要重复录入！");
        }
        //验证用户名是否与其他用户的绑定手机相重复
        if (StringUtils.isNotEmpty(user.getMobile())) {
            if (ObjectUtil.isNotNull(this.queryByMobile(user.getMobile()))) {
                throw new MyException("该手机号已存在！");
            }
        }
        user.setCreateTime(new Date());
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        user.setPassword(new Sha256Hash(password, salt).toHex()); //设置密码
        user.setSalt(salt);
        user.setRoleId(user.getRoleIdList().get(0));
        this.save(user);
        //检查角色是否越权
//		checkRole(user);
        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
    }

    @Override
    public PageUtils querySysPage(Map<String, Object> params) {
        Page<SysUserEntity> page = new Page<SysUserEntity>(Long.valueOf(params.get("page") + ""), Long.valueOf(params.get("limit") + ""));
        List<SysUserEntity> list = baseMapper.querySysPage(page, params);
        page.setRecords(list);
        return new PageUtils((IPage<?>) page);
    }

}
